/****************************************************************************
 * Copyright 2009 Huascar A. Sanchez                                        *
 *                                                                          *
 * Licensed under the Apache License, Version 2.0 (the "License");          *
 * you may not use this file except in compliance with the License.         *
 * You may obtain a copy of the License at                                  *
 *                                                                          *
 *     http://www.apache.org/licenses/LICENSE-2.0                           *
 *                                                                          *
 * Unless required by applicable law or agreed to in writing, software      *
 * distributed under the License is distributed on an "AS IS" BASIS,        *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
 * See the License for the specific language governing permissions and      *
 * limitations under the License.                                           *
 ****************************************************************************/
package com.gotobject.filter.transformation;

import com.gotobject.filter.internal.Objects;
import com.gotobject.filter.spi.Function;
import com.gotobject.filter.spi.TypeLiteral;

/**
 * worked on already filtered out <strong>sets</strong> of objects.
 * @author huascar.sanchez@gmail.com (Huascar A. Sanchez)
 */
public abstract class Transformation<O> implements Function<Object, Iterable<O>> {
    /**
     * Convenience method to transform and cast result.
     * <br><strong>Note:</strong> this method should be used when there is an agreement between
     * the api's consumer and producer. In other words, the developer should
     * make sure that the implementation of the {@link #apply(Object)} complies
     * with the consumer's expected type.
     *
     * @param me
     *      object to be cast.
     * @param to @return
     *      the result of transform
     * @return
     *      cast object.
     * @throws Exception
     *      thrown if the object could not be cast
     *      into an Iterable object.
     */    
    public <T> T cast(Object me, Class<T> to) throws Exception {
        return Objects.cast(me, to);
    }

    /**
     * Convenience method to transform and cast result as an Iterable object.
     * <br><strong>Note:</strong> this is the default casting mechanism for FilterQ.
     *
     * @param o
     *      object to be cast as {@code iterable} object.
     * @return
     *      {@code iterable object}
     * @throws Exception
     *      thrown if the object could not be cast
     *      to an Iterable object.
     */
    public <R extends O> Iterable<R> iterable(Object o) throws Exception {
        return cast(apply(o), new TypeLiteral<Iterable<R>>(){}.getGenericClass());
    }

    /**
     * transform an object into another object.
     * @param me
     *      object to be transformed.
     * @return
     *      the result of the transformation.
     * @throws Exception
     *      thrown if x could not be transformed
     *      into the desired form.
     */
    public abstract Iterable<O> apply(Object me) throws Exception;
}
